package siwi.map.android;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import siwi.map.android.MyAnimations.AnimationsTogetherDone;
import siwi.map.android.MyAnimations.Point;
import siwi.map.android.MyHome.ExAdapter.Holder;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseExpandableListAdapter;
import android.widget.Button;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupClickListener;
import android.widget.ExpandableListView.OnGroupCollapseListener;
import android.widget.ExpandableListView.OnGroupExpandListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockFragment;
import com.actionbarsherlock.view.MenuItem;
import com.wmw.DataPool.OrdersData;
import com.wmw.Utility.Common;
import com.wmw.Utility.DBConstant;
import com.wmw.Utility.DBConstant.DatabaseHelper;
import com.wmw.Utility.Dish;
import com.wmw.Utility.MSG;

public class Orders extends SherlockFragment implements Home.OnFragmentListener {
	// 分类名称为空时,crash
	// 自增ID,满了怎么办
	public static final int _MODIFY_DATA_OK = 1;

	private DatabaseHelper _openDBHelper;

	View _v;
	// 1.输入半角全角字符处理为统一的半角
	private static final String TAG = "ExListView";
	private static final int _MenuAddClassify = Menu.FIRST;

	OrdersData _ordersData;
	List<Map<String, Object>> groupData;
	List<List<Map<String, Object>>> childData;
	Map<Integer, View> groupView = new HashMap<Integer, View>();

	ExAdapter adapter;
	ExpandableListView exList;

	private boolean areButtonsShowing;

	private RelativeLayout composerButtonsWrapper;

	int _prevLeft;
	int _prevTop;
	int _screenWidth;
	int _screenHeight;
	int lastX;
	int lastY;
	View _curSelectedImageButton;
	View _curSelectedViewParent;

	int _selectedGroupPos, _selectedChildPos;
	static int _idx = 0;
	Handler _handler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MSG.GetChildrenCnt:
				int childCnt = exList.getChildCount();
				for (int i = 0; i < childCnt; ++i) {
					View v = exList.getChildAt(i);
				}
				Log.d(Common.GetLineInfo(), "handleMessage");
				Log.d(Common.GetLineInfo(), "list children count is -"
						+ childCnt);

				break;

			case MSG.DeleteThisDish: {
				// Remove it.
				Map<String, Object> dishData = childData.get(_selectedGroupPos)
						.get(_selectedChildPos);
				Dish dish = (Dish) dishData.get(OrdersData._Dish);
				Log.d(Common.GetLineInfo(), "Delete this dish");
				if (removeDish(dish.getName()))
					childData.get(_selectedGroupPos).remove(_selectedChildPos);
				else
					Toast.makeText(getActivity(), "删除失败, 未知错误, 请联系管理员",
							Toast.LENGTH_SHORT).show();

				adapter.notifyDataSetChanged();
			}

				break;

			case MSG.ModifyThisDish: {

				Bundle bundle = msg.getData();

				Map<String, Object> dishData = childData.get(_selectedGroupPos)
						.get(_selectedChildPos);
				Dish dish = (Dish) dishData.get(OrdersData._Dish);

				String prevName = dish.getName();
				float prevPrice = dish.getPrice();
				Dish.DishSalesState prevState = dish.getSaleState();
				int prevLeftNum = dish.getLeftNum();
				String curName = bundle.getString(MSG.DishName);
				float curPrice = bundle.getFloat(MSG.DishPrice);
				Dish.DishSalesState curState = (Dish.DishSalesState) bundle
						.getSerializable(MSG.DishSaleState);
				// Just modify current sales state.
				if (prevName.equals(curName)
						&& (Float.floatToIntBits(prevPrice) == Float
								.floatToIntBits(curPrice))) {
					dish.setSaleState(curState);

					if (curState == Dish.DishSalesState.LEFT_A_FEW) {
						int leftNum = bundle.getInt(MSG.DishLeftNum);
						// WheelView的BUG,android:layout_height设为非wrap_content时,指向的位置会有点偏差.
						if (leftNum == 0)
							leftNum = 100;
						dish.setLeftNum(leftNum);
					}
				} else {
					dish.setName(curName);
					dish.setPrice(curPrice);
					dish.setSaleState(curState);
					if (curState == Dish.DishSalesState.LEFT_A_FEW) {
						int leftNum = bundle.getInt(MSG.DishLeftNum);
						// WheelView的BUG,android:layout_height设为非wrap_content时,指向的位置会有点偏差.
						if (leftNum == 0)
							leftNum = 100;
						dish.setLeftNum(leftNum);
					}

					// Not exists formerly.
					if (!_ordersData.isDishInDB(
							_openDBHelper.getReadableDatabase(), prevName)) {
						if (!insertOneDishToDB(dish)) {
							// Reverse.
							dish.setName(prevName);
							dish.setPrice(prevPrice);
							dish.setSaleState(prevState);
							if (prevState == Dish.DishSalesState.LEFT_A_FEW)
								dish.setLeftNum(prevLeftNum);
							Toast.makeText(getActivity(), "插入失败,已存在的样式",
									Toast.LENGTH_SHORT).show();
						}

					} else {
						if (!_ordersData.isDishInDB(
								_openDBHelper.getReadableDatabase(), curName)) {
							if (!updateDishInDB(prevName, dish,
									(String) groupData.get(_selectedGroupPos)
											.get(DBConstant._CTN_CLASSIFY_NAME))) {
								// Reverse.
								dish.setName(prevName);
								dish.setPrice(prevPrice);
								dish.setSaleState(prevState);
								if (prevState == Dish.DishSalesState.LEFT_A_FEW)
									dish.setLeftNum(prevLeftNum);
								Toast.makeText(getActivity(),
										"修改失败,未知错误,请联系管理员", Toast.LENGTH_SHORT)
										.show();
							}
						}
					}
					Log.d(Common.GetLineInfo(),
							"Get detailed data:" + dish + ", " + dish.getName()
									+ ", " + dish.getSaleState() + ", "
									+ dish.getLeftNum() + ", "
									+ dish.getPrice());

					adapter.notifyDataSetChanged();
				}

			}
				break;

			default:
				break;
			}

		}
	};

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
	}

	/**
	 * When creating, retrieve this instance's number from its arguments.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Bundle bundle = getArguments();
		_openDBHelper = bundle != null ? (DatabaseHelper) bundle
				.getSerializable(MSG.DataBase) : null;
		setHasOptionsMenu(true);
	}

	/**
	 * The Fragment's UI is just a simple text view showing its instance number.
	 */
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		_v = inflater.inflate(R.layout.order_floating_bar, container, false);

		return _v;
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		// insertItem();
		initViews();
		initData();
	}

	@Override
	public void onStart() {
		super.onStart();

		Thread mThreadLoadApps = new Thread() {
			@Override
			public void run() {
				_handler.sendEmptyMessage(MSG.GetChildrenCnt);
			}
		};
		_handler.post(mThreadLoadApps);
	}

	@Override
	public void onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu,
			com.actionbarsherlock.view.MenuInflater inflater) {
		inflater.inflate(R.menu.order_action_bar, menu);

		final MenuItem addMenu = (MenuItem) menu.findItem(R.id.AddNewClassify);
		addMenu.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
			@Override
			public boolean onMenuItemClick(MenuItem item) {
				Log.d(Common.GetLineInfo(), "Add a new classify");
				_ordersData.addNewClassify();
				adapter.notifyDataSetChanged();
				return false;
			}
		});
	}

	@Override
	public void onResume() {
		super.onResume();

		Intent intent = getActivity().getIntent();
		Bundle bundle = intent.getExtras();
		Log.d(Common.GetLineInfo(), "bundle -" + bundle);
		if (bundle != null) {
			if (bundle.getString("Orders") != null
					&& bundle.getString("Orders").equals("DishDetail")) {
				Message msg = new Message();
				msg.what = bundle.getInt("DishDetail");
				msg.setData(bundle);
				this._handler.sendMessage(msg);
			}
		}
		// Once activity jump back, groupView's position maybe disorder, so
		// clear all.
		groupView.clear();
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		// You can use the requestCode to select between multiple child
		// activities you may have started. Here there is only one thing
		// we launch.
		if (requestCode == _MODIFY_DATA_OK) {
			Log.d(Common.GetLineInfo(), "-");
			getActivity().setIntent(data);
			//
			// // We will be adding to our text.
			// Editable text = (Editable) mResults.getText();
			//
			// // This is a standard resultCode that is sent back if the
			// // activity doesn't supply an explicit result. It will also
			// // be returned if the activity failed to launch.
			// if (resultCode == Activity.RESULT_CANCELED) {
			// text.append("(cancelled)");
			//
			// // Our protocol with the sending activity is that it will send
			// // text in 'data' as its result.
			// } else {
			// text.append("(okay ");
			// text.append(Integer.toString(resultCode));
			// text.append(") ");
			// if (data != null) {
			// text.append(data.getAction());
			// }
			// }
			//
			// text.append("\n");
		}
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	static Orders newInstance(DatabaseHelper dbHelper) {
		Log.d(Common.GetLineInfo(), "Creating Orders");
		Orders f = new Orders();

		// Supply num input as an argument.
		Bundle args = new Bundle();
		args.putSerializable(MSG.DataBase, (Serializable) dbHelper);
		f.setArguments(args);

		return f;
	}

	private void initData() {
		final Activity activity = getActivity();

		DisplayMetrics dm = getResources().getDisplayMetrics();
		_screenWidth = dm.widthPixels;
		_screenHeight = dm.heightPixels - 50;

		ExApplication app = (ExApplication) activity.getApplication();
		_ordersData = app._ordersData;
		groupData = app._ordersData.groupData;
		childData = app._ordersData.childData;

		adapter = new ExAdapter(Orders.this);
		exList.setAdapter(adapter);
		exList.setGroupIndicator(null);
		exList.setOnChildClickListener(new onChildClickListenerImpl());// 子被选中
		exList.setOnGroupClickListener(new onGroupClickListenerImpl());// 分组被选中
		exList.setOnGroupExpandListener(new onGroupExpandListenerImpl());// 组展开操作
		exList.setOnGroupCollapseListener(new onGroupCollapseListenerImpl());// 组关闭的操作
		exList.setOnScrollListener(new OnScrollListenerImpl());
		exList.setOnLongClickListener(new OnLongClickListenerImpl());
		exList.setDivider(null);

		adapter.notifyDataSetChanged();
	}

	private void initViews() {
		final Activity activity = getActivity();

		exList = (ExpandableListView) activity.findViewById(R.id.OFB_List);

		MyAnimations.initOffset(activity);
		MyAnimations.setAnimDoneObj(new AnimationsTogetherDone() {
			@Override
			public void onAnimationDone() {
				setControlsPos();
			}
		});

		composerButtonsWrapper = (RelativeLayout) activity
				.findViewById(R.id.composer_buttons_wrapper);

		View deleteControl = composerButtonsWrapper
				.findViewById(R.id.O_F_B_Delete);
		deleteControl.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (_curSelectedImageButton != null) {
					View view = (View) _curSelectedImageButton.getParent();
					ImageButton ib = (ImageButton) view
							.findViewById(R.id.ODC_FunctionalButton);
					final TextView tvClassifyName = (TextView) view
							.findViewById(R.id.O_D_C_Name);
					int idx = -1;
					if (groupView.containsValue(ib)) {
						idx = Common.GetKeyByValue(groupView, ib);
						// Remove it.
						if (removeClassify(tvClassifyName.getText().toString()))
							removeClassify(idx);
					}
					Log.d(Common.GetLineInfo(), "Removing -" + idx + "-th item");
					hideControls();
					// TODO 加上确认对话框
					Log.d(Common.GetLineInfo(),
							"selected item -" + exList.getSelectedItem()
									+ ", idx -" + idx);
				}
			}
		});

		View addControl = composerButtonsWrapper.findViewById(R.id.O_F_B_Add);
		addControl.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				_ordersData.addNewClassify();
				adapter.notifyDataSetChanged();
				hideControls();
			}
		});

		View addDishControl = composerButtonsWrapper
				.findViewById(R.id.O_F_B_Add_Dish);
		addDishControl.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (_curSelectedImageButton != null) {
					View view = (View) _curSelectedImageButton.getParent();
					ImageButton ib = (ImageButton) view
							.findViewById(R.id.ODC_FunctionalButton);
					final TextView tvClassifyName = (TextView) view
							.findViewById(R.id.O_D_C_Name);
					if (!isClassifyInDB(tvClassifyName.getText().toString())) {
						Toast.makeText(getActivity(), "请先修改分类名称",
								Toast.LENGTH_SHORT).show();
					} else {
						int idx = -1;
						if (groupView.containsValue(ib)) {
							idx = Common.GetKeyByValue(groupView, ib);
							List<Map<String, Object>> data = childData.get(idx);
							Log.d(Common.GetLineInfo(),
									"groupView idx in addDishControl is -"
											+ idx);
							// TODO
							data.add(_ordersData.createOneDish("新菜式(如香干炒肉)", 0,
									Dish.DishSalesState.FOR_SALE, 10, 0, 0, 0,
									0));
						}

						adapter.notifyDataSetChanged();
						// TODO 加上确认对话框
						Log.d(Common.GetLineInfo(),
								"selected item -" + exList.getSelectedItem()
										+ ", idx -" + idx);
					}
				}
			}
		});

		View modifyControl = composerButtonsWrapper
				.findViewById(R.id.O_F_B_Modify);
		modifyControl.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				View view = (View) _curSelectedImageButton.getParent();
				ImageButton ib = (ImageButton) view
						.findViewById(R.id.ODC_FunctionalButton);
				final TextView tvClassifyName = (TextView) view
						.findViewById(R.id.O_D_C_Name);
				if (groupView.containsValue(ib)) {
					final int idx = Common.GetKeyByValue(groupView, ib);

					MyDialog dialog = new MyDialog();
					dialog.CreateADialog(getActivity(), tvClassifyName, 10,
							new MyDialog.Sure() {
								@Override
								public void onClickSure(String str) {
									if (isClassifyInDB(str)) {
										Toast.makeText(getActivity(),
												"修改失败,已经存在的分类",
												Toast.LENGTH_SHORT).show();
									} else {
										boolean modifySuccess = true;
										int salesNum = (Integer) groupData.get(
												idx).get(
												DBConstant._CTN_TOTAL_SALES);
										String prevStr = tvClassifyName
												.getText().toString();
										if (isClassifyInDB(prevStr)) {
											// Modify in database.
											if (!(modifySuccess = updateClassifyInDB(
													prevStr, str, salesNum)))
												Toast.makeText(getActivity(),
														"修改失败,未知错误,请联系管理员",
														Toast.LENGTH_SHORT)
														.show();
										} else {
											// Insert into database.
											if (!(modifySuccess = insertOneClassifyToDB(
													str, salesNum)))
												Toast.makeText(getActivity(),
														"修改失败,未知错误,请联系管理员",
														Toast.LENGTH_SHORT)
														.show();
										}

										if (modifySuccess) {
											tvClassifyName.setText(str);
											Map<String, Object> newName = new HashMap<String, Object>();
											newName.put(
													DBConstant._CTN_CLASSIFY_NAME,
													str);
											newName.put(
													DBConstant._CTN_TOTAL_SALES,
													salesNum);
											groupData.set(idx, newName);
										}
									}
									tvClassifyName
											.setBackgroundColor(Orders.this
													.getResources()
													.getColor(
															R.color.Transparent));
								}
							});
				}
				hideControls();

			}
		});
	}

	private boolean updateDishInDB(String prevStr, Dish dish,
			String belongClassify) {
		boolean success = false;
		SQLiteDatabase db = _openDBHelper.getReadableDatabase();

		// 什么是ContentValues类？
		// ContentValues类和Hashtable比较类似，它也是负责存储一些名值对，但是它存储的名值对当中的名是一个String类型，而值都是基本类型。
		ContentValues args = new ContentValues();
		args.put(DBConstant._DTN_DishName, dish.getName());
		args.put(DBConstant._DTN_Price, dish.getPrice());
		args.put(DBConstant._DTN_TotalSales, dish.getTotalSales());
		args.put(DBConstant._DTN_SaleState, dish.getSaleState().ordinal());
		args.put(DBConstant._DTN_LeftNum, dish.getLeftNum());
		args.put(DBConstant._DTN_PositiveCommentCnt,
				dish.getPositiveCommentsCnt());
		args.put(DBConstant._DTN_ModerateCommentCnt,
				dish.getModerateCommentsCnt());
		args.put(DBConstant._DTN_NegativeCommentCnt,
				dish.getNegativeCommentsCnt());
		args.put(DBConstant._DTN_BelongClassify, belongClassify);

		try {
			Log.d(Common.GetLineInfo(), "update database success");
			db.update(DBConstant._DishTableName, args, DBConstant._DTN_DishName
					+ "=='" + prevStr + "'", null);
			success = true;
		} catch (SQLException e) {
			Log.e(Common.GetLineInfo(),
					"update database failure" + e.getStackTrace());
		}

		return success;
	}

	private boolean removeDish(String dishName) {
		boolean success = false;
		try {
			SQLiteDatabase db = _openDBHelper.getWritableDatabase();
			// 第一个参数是数据库表名，在这里是TABLE_NAME，也就是diary。
			// 第二个参数，相当于SQL语句当中的where部分，也就是描述了删除的条件。
			// 如果在第二个参数当中有“？”符号，那么第三个参数中的字符串会依次替换在第二个参数当中出现的“？”符号。
			db.delete(DBConstant._DishTableName, DBConstant._DTN_DishName
					+ "==" + "'" + dishName + "'", null);
			Log.d(Common.GetLineInfo(), "remove from database success");
			success = true;
		} catch (SQLException e) {
			Log.e(Common.GetLineInfo(), "remove from database failue");
		}

		return success;
	}

	private boolean insertOneDishToDB(Dish dish) {
		boolean success = false;
		SQLiteDatabase db = _openDBHelper.getWritableDatabase();

		int id = _ordersData.getClassifyID(
				_openDBHelper.getReadableDatabase(),
				groupData.get(_selectedGroupPos)
						.get(DBConstant._CTN_CLASSIFY_NAME).toString());
		Log.d(Common.GetLineInfo(), "id -" + id);
		String sql1 = "insert into " + DBConstant._DishTableName + " ("
				+ DBConstant._DTN_DishName + ", " + DBConstant._DTN_Price
				+ ", " + DBConstant._DTN_TotalSales + ", "
				+ DBConstant._DTN_SaleState + ", " + DBConstant._DTN_LeftNum
				+ ", " + DBConstant._DTN_PositiveCommentCnt + ", "
				+ DBConstant._DTN_ModerateCommentCnt + ", "
				+ DBConstant._DTN_NegativeCommentCnt + ", "
				+ DBConstant._DTN_BelongClassify + ") values('"
				+ dish.getName() + "', " + dish.getPrice() + ","
				+ dish.getTotalSales() + "," + dish.getSaleState().ordinal()
				+ "," + dish.getLeftNum() + "," + dish.getPositiveCommentsCnt()
				+ "," + dish.getModerateCommentsCnt() + ","
				+ dish.getNegativeCommentsCnt() + ", '" + id + "');";
		try {
			Log.d(Common.GetLineInfo(), "sql -" + sql1);
			db.execSQL(sql1);
			Log.d(Common.GetLineInfo(), "insert into database success");
			success = true;
		} catch (SQLException e) {
			Log.e(Common.GetLineInfo(),
					"insert into database failure" + e.getStackTrace());
		}

		return success;
	}

	private boolean updateClassifyInDB(String prevClassifyName,
			String classifyName, int salesNum) {
		boolean success = false;
		SQLiteDatabase db = _openDBHelper.getReadableDatabase();

		// 什么是ContentValues类？
		// ContentValues类和Hashtable比较类似，它也是负责存储一些名值对，但是它存储的名值对当中的名是一个String类型，而值都是基本类型。
		ContentValues args = new ContentValues();
		args.put(DBConstant._CTN_CLASSIFY_NAME, classifyName);
		args.put(DBConstant._CTN_TOTAL_SALES, salesNum);

		try {
			Log.d(Common.GetLineInfo(), "update database success");
			db.update(DBConstant._ClassifyTableName, args,
					DBConstant._CTN_CLASSIFY_NAME + "=='" + prevClassifyName
							+ "'", null);
			success = true;
		} catch (SQLException e) {
			Log.e(Common.GetLineInfo(),
					"update database failure" + e.getStackTrace());
		}

		return success;
	}

	private boolean insertOneClassifyToDB(String classifyName, int salesNum) {
		boolean success = false;
		SQLiteDatabase db = _openDBHelper.getWritableDatabase();
		String sql1 = "insert into " + DBConstant._ClassifyTableName + " ("
				+ DBConstant._CTN_CLASSIFY_NAME + ", "
				+ DBConstant._CTN_TOTAL_SALES + ") values('" + classifyName
				+ "'," + salesNum + ");";
		try {
			Log.d(Common.GetLineInfo(), "sql -" + sql1);
			db.execSQL(sql1);
			Log.d(Common.GetLineInfo(), "insert into database success");
			success = true;
		} catch (SQLException e) {
			Log.e(Common.GetLineInfo(),
					"insert into database failure" + e.getStackTrace());
		}

		return success;
	}

	private boolean isClassifyInDB(String classifyName) {
		SQLiteDatabase db = _openDBHelper.getReadableDatabase();
		String col[] = { DBConstant._CTN_CLASSIFY_NAME };
		String[] selectionArgs = { classifyName };
		// 查询数据
		Cursor cur = db.query(DBConstant._ClassifyTableName, col,
				DBConstant._CTN_CLASSIFY_NAME + "==?", selectionArgs, null,
				null, null);
		return cur.getCount() != 0;
	}

	private boolean removeClassify(String classifyName) {
		boolean success = false;
		try {
			SQLiteDatabase db = _openDBHelper.getWritableDatabase();
			// 第一个参数是数据库表名，在这里是TABLE_NAME，也就是diary。
			// 第二个参数，相当于SQL语句当中的where部分，也就是描述了删除的条件。
			// 如果在第二个参数当中有“？”符号，那么第三个参数中的字符串会依次替换在第二个参数当中出现的“？”符号。
			db.execSQL("PRAGMA foreign_keys=1;");
			db.delete(DBConstant._ClassifyTableName,
					DBConstant._CTN_CLASSIFY_NAME + "==" + "'" + classifyName
							+ "'", null);
			Log.d(Common.GetLineInfo(), "remove from database success");
			success = true;
		} catch (SQLException e) {
			Log.e(Common.GetLineInfo(), "remove from database failue");
		}

		return success;
	}

	//
	// private Map<String, Object> createOneDish(String dishName, int
	// totalSales,
	// Dish.DishSalesState salesState, float price,
	// int positiveCommentsCnt, int moderateCommentsCnt,
	// int negativeCommentsCnt) {
	// Log.d(Common.GetLineInfo(), "Creating one dish");
	// Map<String, Object> curChildMap = new HashMap<String, Object>();
	// Dish dish = new Dish(dishName, totalSales, salesState, price,
	// positiveCommentsCnt, moderateCommentsCnt, negativeCommentsCnt);
	// curChildMap.put(_Dish, dish);
	// return curChildMap;
	// }

	// private void addNewClassify() {
	// addNewClassify("新分类(如十元特色菜)" + _idx++, 0);
	// }

	// private void addNewClassify(String classifyName, int salesNum) {
	// Map<String, Object> curGroupMap = new HashMap<String, Object>();
	// groupData.add(curGroupMap);
	// curGroupMap.put(DBConstant._CTN_CLASSIFY_NAME, classifyName);
	// curGroupMap.put(DBConstant._CTN_TOTAL_SALES, salesNum);
	//
	// List<Map<String, Object>> children = new ArrayList<Map<String,
	// Object>>();
	// childData.add(children);
	// }

	private void removeClassify(int idx) {
		Log.d(Common.GetLineInfo(), "Remove groupData -" + groupData.get(idx)
				+ ", childData -" + childData.get(idx) + ", groupView -"
				+ groupView.get(idx));
		groupData.remove(idx);
		childData.remove(idx);
		groupView.remove(idx);
		adapter.notifyDataSetChanged();
	}

	private void hideControls() {
		if (areButtonsShowing) {
			MyAnimations.StartAnimationsTogether(composerButtonsWrapper,
					MyAnimations.DurationMS, new Point(_prevLeft, _prevTop),
					false);
			areButtonsShowing = !areButtonsShowing;
		}
		// 分组可能会改变View的位置,所以需要重设为空.
		_curSelectedImageButton = null;
	}

	private void setControlsPos() {
		int controlsNum = composerButtonsWrapper.getChildCount();

		Log.d(Common.GetLineInfo(), "previous left -" + _prevLeft
				+ ", previous top -" + _prevTop);
		// Map (x,y) Coordinate System to (y, x) Coordinate System.
		Point[] points = new Point[controlsNum];
		for (int i = 0; i < points.length; ++i)
			points[i] = new Point(_prevTop, _prevLeft);
		Point center = new Point(_prevTop, _prevLeft);

		int radius = 150;
		int startDegree = 0, endDegree = 180;
		boolean includeStartAndEndDegree = false;
		// Decide start degree and end degree.
		if (center._x - radius < -55) {
			endDegree = 90;
			includeStartAndEndDegree = true;
		} else if (center._x + radius > _screenHeight - 105) {
			// 50 is for tabs of bottom.
			startDegree = 90;
			includeStartAndEndDegree = true;
		}
		Log.d(Common.GetLineInfo(), "startDegree -" + startDegree
				+ ", endDegree -" + endDegree + ", radius -" + radius
				+ ", center._x -" + center._x + ", _screenHeight -"
				+ _screenHeight);

		MyAnimations.SetControlsPosition(points, center, radius, controlsNum,
				startDegree, endDegree, includeStartAndEndDegree);

		int left, top;
		for (int i = 0; i < controlsNum; ++i) {
			left = points[i]._y;
			top = points[i]._x;
			ImageButton imagebtn = (ImageButton) composerButtonsWrapper
					.getChildAt(i);
			int right = _screenWidth - left - imagebtn.getWidth();
			int bottom = _screenHeight - top - imagebtn.getHeight();
			RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
					LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
			Log.d(Common.GetLineInfo(), "animation views' positions:left -"
					+ left + ", top -" + top + ", right -" + right
					+ ", bottom -" + bottom);
			params.setMargins(left, top, right, bottom);
			imagebtn.setLayoutParams(params);
		}

		MyAnimations.StartAnimationsSpread(composerButtonsWrapper,
				MyAnimations.DurationMS, new Point(_prevLeft, _prevTop));
		areButtonsShowing = true;
	}

	private class onGroupCollapseListenerImpl implements
			OnGroupCollapseListener {
		public void onGroupCollapse(int groupPosition) {
			// View view = _curSelectedViewParent;
			// final ImageView ivArrow = (ImageView) view
			// .findViewById(R.id.O_D_C_Arrow);
			// ivArrow.setImageResource(R.drawable.list_close_arrow);
			hideControls();
			Log.d(Common.GetLineInfo(), "关闭分组,groupPosition=" + groupPosition);
		}
	}

	private class OnLongClickListenerImpl implements OnLongClickListener {

		@Override
		public boolean onLongClick(View arg0) {
			Log.d(Common.GetLineInfo(), "-");
			return false;
		}

	}

	private class OnScrollListenerImpl implements OnScrollListener {
		@Override
		public void onScrollStateChanged(AbsListView view, int scrollState) {
			hideControls();
		}

		@Override
		public void onScroll(AbsListView view, int firstVisibleItem,
				int visibleItemCount, int totalItemCount) {
		}

	}

	private class onGroupExpandListenerImpl implements OnGroupExpandListener {
		public void onGroupExpand(int groupPosition) {
			// View view = _curSelectedViewParent;
			// final ImageView ivArrow = (ImageView) view
			// .findViewById(R.id.O_D_C_Arrow);
			// ivArrow.setImageResource(R.drawable.list_open_arrow);
			hideControls();
			Log.d(Common.GetLineInfo(), "打开分组,groupPosition=" + groupPosition);
		}
	}

	private class onGroupClickListenerImpl implements OnGroupClickListener {

		public boolean onGroupClick(ExpandableListView parent, View v,
				int groupPosition, long id) {
			_curSelectedViewParent = v;
			TextView tv = (TextView) v.findViewById(R.id.O_D_C_Name);
			Log.d(Common.GetLineInfo(), "组被选中,groupPosition=" + groupPosition
					+ ", text -" + tv.getText());
			return false;
		}
	}

	private class onChildClickListenerImpl implements OnChildClickListener {
		public boolean onChildClick(ExpandableListView parent, View v,
				int groupPosition, int childPosition, long id) {
			Log.d(Common.GetLineInfo(), "子被选中,groupPosition -" + groupPosition
					+ ", childPosition -" + childPosition);

			_selectedGroupPos = groupPosition;
			_selectedChildPos = childPosition;
			// TODO
			Map<String, Object> dishData = adapter.getChild(groupPosition,
					childPosition);
			Dish dish = (Dish) dishData.get(OrdersData._Dish);
			Intent intent = new Intent();
			intent.setClass(getActivity(), DishDetail.class);
			intent.putExtra(MSG.Dish, dish);
			startActivityForResult(intent, _MODIFY_DATA_OK);

			return false;
		}
	}

	//
	// private void insertItem() {
	// // mOpenHelper.getWritableDatabase()语句负责得到一个可写的SQLite数据库，如果这个数据库还没有建立，
	// // 那么mOpenHelper辅助类负责建立这个数据库。如果数据库已经建立，那么直接返回一个可写的数据库。
	// SQLiteDatabase db = _openDBHelper.getWritableDatabase();
	// String sql1 = "insert into " + DBConstant._ClassifyTableName + " ("
	// + DBConstant._CTN_CLASSIFY_NAME + ", "
	// + DBConstant._CTN_TOTAL_SALES + ") values('数据库表分类1', 0);";
	// String sql2 = "insert into " + DBConstant._ClassifyTableName + " ("
	// + DBConstant._CTN_CLASSIFY_NAME + ", "
	// + DBConstant._CTN_TOTAL_SALES + ") values('数据库表分类2', 0);";
	// try {
	// Log.d(Common.GetLineInfo(), "sql1" + sql1);
	// Log.d(Common.GetLineInfo(), "sql2" + sql2);
	// db.execSQL(sql1);
	// db.execSQL(sql2);
	// Log.d(Common.GetLineInfo(), "insert into database success");
	// } catch (SQLException e) {
	// Log.e(Common.GetLineInfo(), "insert into database failure");
	// }
	//
	// sql1 = "insert into " + DBConstant._DishTableName + " ("
	// + DBConstant._DTN_DishName + ", " + DBConstant._DTN_Price
	// + ", " + DBConstant._DTN_TotalSales + ", "
	// + DBConstant._DTN_SaleState + ", " + DBConstant._DTN_LeftNum
	// + ", " + DBConstant._DTN_PositiveCommentCnt + ", "
	// + DBConstant._DTN_ModerateCommentCnt + ", "
	// + DBConstant._DTN_NegativeCommentCnt + ", "
	// + DBConstant._DTN_BelongClassify
	// + ") values('新菜式(如香干炒肉)', 10, 0, 0, 100, 0, 0, 0, '数据库表分类1');";
	//
	// sql2 = "insert into " + DBConstant._DishTableName + " ("
	// + DBConstant._DTN_DishName + ", " + DBConstant._DTN_Price
	// + ", " + DBConstant._DTN_TotalSales + ", "
	// + DBConstant._DTN_SaleState + ", " + DBConstant._DTN_LeftNum
	// + ", " + DBConstant._DTN_PositiveCommentCnt + ", "
	// + DBConstant._DTN_ModerateCommentCnt + ", "
	// + DBConstant._DTN_NegativeCommentCnt + ", "
	// + DBConstant._DTN_BelongClassify
	// + ") values('新菜式(如香干炒肉)2', 10, 0, 0, 100, 0, 0, 0, '数据库表分类2');";
	// try {
	// Log.d(Common.GetLineInfo(), "sql1" + sql1);
	// Log.d(Common.GetLineInfo(), "sql2" + sql2);
	// db.execSQL(sql1);
	// db.execSQL(sql2);
	// Log.d(Common.GetLineInfo(), "insert into database success");
	// } catch (SQLException e) {
	// Log.e(Common.GetLineInfo(),
	// "insert into database failure" + e.getStackTrace());
	// }
	// }

	/*
	 * 在屏幕的title区域显示当前数据表当中的数据的条数。
	 */
	/*
	 * Cursor cur = db.query(TABLE_NAME, col, null, null, null, null,
	 * null)语句将查询到的数据放到一个Cursor 当中。 这个Cursor里边封装了这个数据表TABLE_NAME当中的所有条列。
	 * query()方法相当的有用，在这里我们简单地讲一下。
	 * 第一个参数是数据库里边表的名字，比如在我们这个例子，表的名字就是TABLE_NAME，也就是"diary"。
	 * 第二个字段是我们想要返回数据包含的列的信息。在这个例子当中我们想要得到的列有title、body。我们把这两个列的名字放到字符串数组里边来。
	 * 第三个参数为selection，相当于SQL语句的where部分，如果想返回所有的数据，那么就直接置为null。
	 * 第四个参数为selectionArgs
	 * 。在selection部分，你有可能用到“?”，那么在selectionArgs定义的字符串会代替selection中的“?”。
	 * 第五个参数为groupBy。定义查询出来的数据是否分组，如果为null则说明不用分组。 第六个参数为having
	 * ，相当于SQL语句当中的having部分。 第七个参数为orderBy，来描述我们期望的返回值是否需要排序，如果设置为null则说明不需要排序。
	 */
	//
	// private void showItems(SQLiteDatabase db) {
	// String col[] = { DBConstant._CTN_CLASSIFY_NAME,
	// DBConstant._CTN_TOTAL_SALES };
	// // 查询数据
	// Cursor cur = db.query(DBConstant._ClassifyTableName, col, null, null,
	// null, null, null);
	// Integer num = cur.getCount();
	// Log.d(Common.GetLineInfo(), "records number -" + num);
	//
	// for (int i = 0; i < num; i++) {
	// if (cur.moveToFirst()) {// 判断游标是否为空
	// cur.move(i);// 移动到指定记录
	// String classifyStr = cur.getString(cur
	// .getColumnIndex(DBConstant._CTN_CLASSIFY_NAME));
	// this.addNewClassify(classifyStr, cur.getInt(cur
	// .getColumnIndex(DBConstant._CTN_TOTAL_SALES)));
	//
	// Cursor subCur = db.query(DBConstant._DishTableName, null,
	// DBConstant._DTN_BelongClassify + "=='" + classifyStr
	// + "'", null, null, null, null);
	// int subNum = subCur.getCount();
	// Log.d(Common.GetLineInfo(), "records number -" + subNum);
	//
	// List<Map<String, Object>> data = childData.get(i);
	// for (int j = 0; j < subNum; ++j) {
	// if (subCur.moveToFirst()) {// 判断游标是否为空
	// subCur.move(j);// 移动到指定记录
	//
	// int dishNameIdx = subCur
	// .getColumnIndex(DBConstant._DTN_DishName);
	// Log.d(Common.GetLineInfo(), "dishNameIdx -"
	// + dishNameIdx);
	// Map<String, Object> dish = createOneDish(
	// subCur.getString(dishNameIdx),
	// subCur.getInt(subCur
	// .getColumnIndex(DBConstant._DTN_TotalSales)),
	// Dish.DishSalesState.values()[subCur.getInt(subCur
	// .getColumnIndex(DBConstant._DTN_SaleState))],
	// subCur.getFloat(subCur
	// .getColumnIndex(DBConstant._DTN_Price)),
	// subCur.getInt(subCur
	// .getColumnIndex(DBConstant._DTN_PositiveCommentCnt)),
	// subCur.getInt(subCur
	// .getColumnIndex(DBConstant._DTN_ModerateCommentCnt)),
	// subCur.getInt(subCur
	// .getColumnIndex(DBConstant._DTN_NegativeCommentCnt)));
	// data.add(dish);
	// }
	// }
	// subCur.close();
	// }
	// }
	//
	// }

	class ExAdapter extends BaseExpandableListAdapter {
		Orders exlistview;

		class Holder {
			private TextView _name, _salesNum, _classifyCount;
			private ImageView _arrow;
			private ImageButton _functionalButton;
		}

		public ExAdapter(Orders elv) {
			super();
			exlistview = elv;
		}

		@Override
		public View getGroupView(int groupPosition, boolean isExpanded,
				View convertView, ViewGroup parent) {
			Holder holder = null;
			View view = convertView;
			Log.d(Common.GetLineInfo(), "view -" + view + ", parent -" + parent
					+ ", idx -" + groupPosition);
			if (view == null) {
				LayoutInflater inflater = (LayoutInflater) getActivity()
						.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				view = inflater.inflate(R.layout.order_dishes_classify, null);
				holder = new Holder();
				holder._name = (TextView) view.findViewById(R.id.O_D_C_Name);
				holder._salesNum = (TextView) view
						.findViewById(R.id.ODC_SalesNum);
				holder._classifyCount = (TextView) view
						.findViewById(R.id.O_D_C_ClassifyCount);
				holder._arrow = (ImageView) view.findViewById(R.id.O_D_C_Arrow);
				holder._functionalButton = (ImageButton) view
						.findViewById(R.id.ODC_FunctionalButton);
				view.setTag(holder);
			} else
				holder = (Holder) view.getTag();

			Map<String, Object> curGroupMap = groupData.get(groupPosition);
			String str = (String) curGroupMap
					.get(DBConstant._CTN_CLASSIFY_NAME);
			holder._name.setText(str);

			int salesNum = (Integer) curGroupMap
					.get(DBConstant._CTN_TOTAL_SALES);
			holder._salesNum.setText("销售量(" + salesNum + ")");

			List<Map<String, Object>> data = childData.get(groupPosition);
			holder._classifyCount.setText("[" + data.size() + "]");
			if (isExpanded)
				holder._arrow.setImageResource(R.drawable.list_open_arrow);
			else
				holder._arrow.setImageResource(R.drawable.list_close_arrow);

			if (!groupView.containsKey(groupPosition)) {
				groupView.put(groupPosition, holder._functionalButton);

				Log.d(Common.GetLineInfo(),
						"groupView's size -" + groupView.size());
				holder._functionalButton
						.setOnClickListener(new Button.OnClickListener() {
							@Override
							public void onClick(View v) {
								int[] location = new int[2];
								v.getLocationOnScreen(location);
								int x = location[0];
								int y = location[1];

								Log.d(Common.GetLineInfo(),
										"image's position:x - " + x + ", y - "
												+ y);

								// 对应控件的位移,测出来的对应位移.
								int left = x + 20;
								int top = y - 71;

								if (v == _curSelectedImageButton) {
									if (!areButtonsShowing)
										MyAnimations.StartAnimationsSpread(
												composerButtonsWrapper,
												MyAnimations.DurationMS,
												new Point(left, top));
									else
										MyAnimations.StartAnimationsTogether(
												composerButtonsWrapper,
												MyAnimations.DurationMS,
												new Point(left, top), false);

									areButtonsShowing = !areButtonsShowing;
									return;
								} else {
									if (areButtonsShowing) {
										MyAnimations.StartAnimationsTogether(
												composerButtonsWrapper,
												MyAnimations.DurationMS,
												new Point(_prevLeft, _prevTop),
												true);
									} else {
										_prevLeft = left;
										_prevTop = top;
										setControlsPos();
									}

									_prevLeft = left;
									_prevTop = top;

									if (_curSelectedImageButton == null)
										setControlsPos();

									_curSelectedImageButton = v;
								}

							}
						});
			}

			return view;
		}

		public long getGroupId(int groupPosition) {
			return groupPosition;
		}

		public Object getGroup(int groupPosition) {
			return groupData.get(groupPosition)
					.get(DBConstant._CTN_CLASSIFY_NAME).toString();
		}

		public int getGroupCount() {
			return groupData.size();
		}

		public View getChildView(int groupPosition, int childPosition,
				boolean isLastChild, View convertView, ViewGroup parent) {
			View view = convertView;
			if (view == null) {
				LayoutInflater inflater = (LayoutInflater) getActivity()
						.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				view = inflater.inflate(R.layout.order_dishes, null);
			}
			Map<String, Object> dishData = adapter.getChild(groupPosition,
					childPosition);
			Dish dish = (Dish) dishData.get(OrdersData._Dish);
			final TextView name = (TextView) view.findViewById(R.id.O_D_Name);
			name.setText(dish.getName());
			final TextView salesNum = (TextView) view
					.findViewById(R.id.OD_SalesVolume);
			salesNum.setText("销售量(" + dish.getTotalSales() + ")");
			final TextView state = (TextView) view.findViewById(R.id.O_D_State);
			Dish.DishSalesState salesState = dish.getSaleState();
			switch (salesState) {
			case FOR_SALE:
				state.setText("待售");
				break;

			case SOLD_OUT:
				state.setText("售完");
				break;

			case LEFT_A_FEW:
				state.setText("余" + dish.getLeftNum() + "份");
				break;

			default:
				Log.d(Common.GetLineInfo(), "Unexpected error!");
				break;
			}
			state.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					Log.d(Common.GetLineInfo(), "Click state");
				}

			});
			return view;
		}

		public long getChildId(int groupPosition, int childPosition) {
			return childPosition;
		}

		public Map<String, Object> getChild(int groupPosition, int childPosition) {
			return childData.get(groupPosition).get(childPosition);
		}

		public int getChildrenCount(int groupPosition) {
			return childData.get(groupPosition).size();
		}

		public boolean hasStableIds() {
			return true;
		}

		public boolean isChildSelectable(int groupPosition, int childPosition) {
			return true;
		}

	}

	@Override
	public void onFragmentResume(Intent intent) {
		// TODO Auto-generated method stub
	}

}